package cn.edu.hznu.coursework.service;

import java.util.List;
import java.util.Optional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import cn.edu.hznu.coursework.entity.Course;
import cn.edu.hznu.coursework.entity.Student;
import cn.edu.hznu.coursework.entity.StudentWork;
import cn.edu.hznu.coursework.entity.Teacher;
import cn.edu.hznu.coursework.entity.TeacherWork;
import cn.edu.hznu.coursework.repository.CourseRepository;
import cn.edu.hznu.coursework.repository.StudentRepository;
import cn.edu.hznu.coursework.repository.StudentWorkRepository;
import cn.edu.hznu.coursework.repository.TeacherRepository;
import cn.edu.hznu.coursework.repository.TeacherWorkRepository;

@Service("TeacherService")
@Transactional(rollbackFor = {Exception.class})
public class TeacherServiceImpl implements TeacherService{
	
	@Autowired
	TeacherRepository teacherRepo;
	@Autowired
	CourseRepository courseRepo;
	@Autowired
	TeacherWorkRepository TeacherWorkRepo;
	@Autowired
	StudentRepository studentRepo;
	@Autowired
	StudentWorkRepository studentWorkRepo;

	@Override
	public Teacher findTeacherById(Integer id) {
		return this.teacherRepo.findOne(id);
	}

	@Override
	public List<Teacher> findAllTeacher() {
		return this.teacherRepo.findAll();
	}
	
	@Override
	public Course findCourseByCourseNameAndCourseNo(String courseName, char courseNo) {
		return this.courseRepo.findByCourseNameAndCourseNo(courseName, courseNo);
	}

	@Override
	public Course findCourseById(Integer id) {
		return this.courseRepo.findOne(id);
	}
	
	@Override
	public List<Course> findCoursesByStudents(List<Student> students) {
		return this.courseRepo.findByStudents(students);
	}
	
	@Override
	public List<Course> findCoursesByTeacher(Teacher teacher) {
		return this.courseRepo.findByTeacher(teacher);
	}

	@Override
	public TeacherWork findTeacherWorkById(Integer id) {
		return this.TeacherWorkRepo.findOne(id);
	}
	
	@Override
	public List<TeacherWork> findTeacherWorkByTeacher(Teacher teacher) {
		return this.TeacherWorkRepo.findByTeacher(teacher);
	}
	
	@Override
	public List<TeacherWork> findTeacherWorkByCourse(Course course) {
		return this.TeacherWorkRepo.findByCourse(course);
	}

	@Override
	public void publishCourse(Teacher teacher, Course course) throws Exception {
		List<Course> publishedCourses = this.courseRepo.findByTeacher(teacher);
		if(publishedCourses.stream()
						   .anyMatch(publishedCourse -> 
									publishedCourse.getCourseName().equals(course.getCourseName()) && 
									publishedCourse.getCourseNo() == course.getCourseNo())){
//			throw new Exception("this course has been published.");
			throw new Exception("该课程已发布。");
		}
		course.setTeacher(teacher);
		this.courseRepo.save(course);
	}

	@Override
	public void removeCourse(Integer id) throws Exception {
		Optional.ofNullable(this.courseRepo.findOne(id))
//		.orElseThrow(() -> new Exception("this course does not exist.")); 
		.orElseThrow(() -> new Exception("该课程不存在。")); 
		this.courseRepo.delete(id);
	}
	
	@Override
	public void publishTeacherWork(Teacher teacher, Course course, TeacherWork work) throws Exception{
		work.setTeacher(teacher);
		work.setCourse(course);
		this.TeacherWorkRepo.save(work);
		// Add new student work to notice this course's students.
		course.getStudents().forEach(student -> {
			StudentWork studentWork = new StudentWork();
			studentWork.setSubmitted(false);
			studentWork.setCourse(course);
			studentWork.setTeacherWork(work);
			studentWork.setStudent(student);
			this.studentWorkRepo.save(studentWork);
		});
	}

	@Override
	public void removeTeacherWork(Integer id) throws Exception {
		Optional.ofNullable(this.TeacherWorkRepo.findOne(id))
//				.orElseThrow(() -> new Exception("this work does not exist."));
				.orElseThrow(() -> new Exception("该作业要求不存在。"));
		this.TeacherWorkRepo.delete(id);
	}

	@Override
	public void addStudent(Student student, Course course) throws Exception {
		if(student.getCourses()
				  .stream()
				  .anyMatch(addedCourse -> addedCourse.equals(course))){
//			throw new Exception("this student has been attended the course");
			throw new Exception("该课程中已经添加此学生。");
		}
		student.getCourses().add(course);
		this.studentRepo.save(student);
		course.getTeacherWorks().forEach(work -> {
			StudentWork studentWork = new StudentWork();
			studentWork.setSubmitted(false);
			studentWork.setCourse(course);
			studentWork.setTeacherWork(work);
			studentWork.setStudent(student);
			this.studentWorkRepo.save(studentWork);
		});
	}

	@Override
	public void removeStudent(Student student, Course course) throws Exception {
		student.getCourses().remove(course);
		this.studentRepo.save(student);
		List<StudentWork> studentWorks = this.studentWorkRepo
				.findByStudentAndCourse(student, course);
		studentWorks.forEach(work -> {
			this.studentWorkRepo.delete(work);
		});
//		student.getWorks().removeIf(work -> work.getCourse().equals(course));
//		this.studentWorkRepo.save(studentWorks);
//		this.studentRepo.save(student);
	}

	@Override
	public void updateStudentWork(List<StudentWork> works) throws Exception{
		this.studentWorkRepo.save(works);
	}
	
}
